<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style>
    .cont{margin: 0 auto;position: relative;}
    .cont .box{padding: 5px;float: left;}
    .cont .box .imgbox{border: solid 1px black;border-radius:4px;padding: 6px;}
    .cont .box .imgbox img{width: 200px;}
    .cont .box h3{width: 200px;}
  </style>
</head>
<body>
  <div class="cont">
  </div>
</body>
<script src="./data.js"></script>
<script>

  // OOA：瀑布流布局
  // 1. 获取元素【属性】
  // 2. 补全布局：数据【属性】，遍历，拼接字符，设置到指定容器【方法】
  // 3. 判断一行最多放几个【属性】
  // 4. 通过第一行获取初始列高【方法】
  // 5. 在其他行中，设置定位【方法】
  // 6. 在其他行获取最小列高作为top【方法】
  // 7. 在其他行获取最小列高的索引用于计算left【方法】
  // 8. 改变列高：原列高 + 新放置元素的高【方法】
  // 9. 从第5步开始重复


  // OOD：
  // function WaterFull( {data, cont} ){
  //   // 获取元素
  //   // 获取数据
  //   // 用来存储初始列高

  //   // 计算一行最多放几个
  //   this.init();
  // }
  // WaterFull.prototype.init = function(){
  //   // 补全布局
  //   this.firstLine()
  //   this.otherLine()
  // }
  // WaterFull.prototype.firstLine = function(){
  //   // 获取第一行的初始高度
  // }
  // WaterFull.prototype.otherLine = function(){
  //   // 获取初始列高的最小值及索引，设置定位等样式
  // }
  // new WaterFull({
  //   data, cont
  // });




  // OOP：
  function WaterFull( {data, cont} ){
    // 获取元素
    this.cont = cont;
    // 获取数据
    this.data = data;
    // 用来存储初始列高
    this.heightArr = [];
    // 渲染页面结构
    this.render();
  }
  WaterFull.prototype.render = function(){
    // 渲染页面结构
    let str = "";
    this.data.forEach(val=>{
      str += `<div class="box">
              <div class="imgbox"><img src="${val.img}" alt=""></div>
              <h3>${val.title}</h3>
            </div>`
    })
    this.cont.innerHTML = str;
    // 获取所有容器
    this.box = this.cont.children;

    // 补全布局
    // 等待浏览器加载完成后，再区分第一行和其他行（要获取资源高度）
    // 当直接将方法作为事件处理函数使用时，在方法内又需要通过this找到实例
    // 该方法需要提前使用bind修改this指向
    window.onload = this.init.bind(this);
  }
  WaterFull.prototype.init = function(){
    // 计算一行最多放几个
    const clientW = document.documentElement.clientWidth;
    this.maxNum = Math.floor(clientW / this.box[0].offsetWidth);
    // 设置容器宽度
    this.cont.style.width = this.maxNum * this.box[0].offsetWidth + "px";
    // 第一行
    this.firstLine()
    // 其他行
    this.otherLine()
  }
  WaterFull.prototype.firstLine = function(){
    for(let i=0;i<this.maxNum;i++){
      this.heightArr.push(this.box[i].offsetHeight);
    }
  }
  WaterFull.prototype.otherLine = function(){
    // 获取初始列高的最小值及索引，设置定位等样式
    for(let i=this.maxNum; i<this.box.length; i++){
      this.box[i].style.position = "absolute";
      const min = Math.min(...this.heightArr);
      const minIndex = this.heightArr.indexOf(min);
      this.box[i].style.top = min + "px";
      this.box[i].style.left = minIndex * this.box[i].offsetWidth + "px";
      this.heightArr[minIndex] += this.box[i].offsetHeight;
    }
  }


  const cont = document.querySelector(".cont");
  new WaterFull({
    data, cont
  });
  




</script>
</html>